package org.sbbs.base.jsf;

import jakarta.faces.application.FacesMessage;
import static jakarta.faces.application.FacesMessage.SEVERITY_ERROR;
import static jakarta.faces.application.FacesMessage.SEVERITY_WARN;
import jakarta.faces.context.FacesContext;
import lombok.extern.slf4j.Slf4j;
import org.omnifaces.util.Messages;
import org.primefaces.PrimeFaces;
import org.primefaces.component.api.UIColumn;
import org.primefaces.event.ColumnToggleEvent;
import org.primefaces.model.DialogFrameworkOptions;
import org.primefaces.model.LazyDataModel;
import org.primefaces.model.Visibility;
import org.sbbs.base.jpa.dao.BaseRepo;
import org.sbbs.base.jpa.entity.BaseEntity;
import org.sbbs.base.jpa.manager.BaseManager;

import java.io.Serializable;
import java.util.List;
import lombok.Data;
import org.joinfaces.primefaces.SpringDataJpaLazyDataModel;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.support.MessageSourceAccessor;

/**
 *
 * @author jenkins
 * @param <T>
 * @param <Id>
 * @param <R>
 * @param <M>
 */
@Slf4j
@Data
public abstract class BaseTableMBean<T extends BaseEntity, Id extends Serializable, R extends BaseRepo, M extends BaseManager> implements Serializable {

    M manager;
    LazyDataModel<T> lazyModel;//
    //页面搜索条件与排序
    Filter<T> filter = new Filter<T>(this.createNewObj());

    @Autowired
    @Qualifier("sma")
    //这个类的定义方式是个学问呀 @important
    private MessageSourceAccessor sma;

    public BaseTableMBean(M m) {
        this.manager = m;
        lazyModel = new SpringDataJpaLazyDataModel(m.getRepo());
    }
    // 单选
    private T singleSelected;
    private List<T> multipleSelected;

    /**
     * 单一对象删除
     */
    public void delSingle() {
        if (singleSelected != null) {
            try {
                manager.remove(singleSelected);
//                Object[] args = {singleSelected.getId()};
                addDetailMessage(sma.getMessage("delete.success"));
            } catch (Exception e) {
                e.printStackTrace();
                addDetailMessage(sma.getMessage("delete.exception"), SEVERITY_ERROR);
            }
        } else {
            addDetailMessage(sma.getMessage("delete.noselected"), SEVERITY_WARN);
        }
    }

    /**
     * 多选对象删除
     */
    public void delMultiple() {
        if (multipleSelected != null && !multipleSelected.isEmpty()) {
            try {
                manager.removeAll(multipleSelected);
                addDetailMessage(sma.getMessage("delete.success"));
            } catch (Exception e) {
                e.printStackTrace();
                addDetailMessage(sma.getMessage("delete.exception"), SEVERITY_ERROR);
            }
        } else {
            addDetailMessage(sma.getMessage("delete.noselected"), SEVERITY_WARN);
        }
    }

    //编辑对象
    private T editObj;

    public abstract T createNewObj();

    public void newOpt(String form) {
        this.editObj = this.createNewObj();
        this.openDialog(form);
    }

    public void editOpt(String form) {
        if (this.multipleSelected.size() > 1) {
            addDetailMessage(sma.getMessage("edit.moreselected"), SEVERITY_WARN);
            return;

        }
        if (this.singleSelected != null || !this.multipleSelected.isEmpty()) {
            if (this.singleSelected != null) {
                this.editObj = this.singleSelected;
            } else {
                this.editObj = this.multipleSelected.getFirst();
            }
            this.openDialog(form);
        } else {
        }
    }

    public void closeDialog() {
//        PrimeFaces.current().dialog().closeDynamic(null);
        PrimeFaces.current().dialog().closeDynamic(this.editObj);
    }
//    public void dialogCancel() {
//        PrimeFaces.current().dialog().closeDynamic(null);
//    }

    public void openDialog(String form) {
//        this.editDict = this.selectedSysDict;
        String outcome = null;
        DialogFrameworkOptions options = DialogFrameworkOptions.builder()
                .resizable(true)
                .draggable(true)
                .modal(true)
                .closeOnEscape(true)
                .maximizable(true)
                .minimizable(true)
                .fitViewport(true)
                .responsive(true)
                .blockScroll(false)
                // “explode”（爆炸效果）、“slide”（滑动效果）、“fade”
                .showEffect("fade")
                .hideEffect("explode")
                .build();
        PrimeFaces.current().dialog().openDynamic(form, options, null);
    }

    public void save() {
        try {
            manager.save(editObj);
            PrimeFaces.current().dialog().closeDynamic(editObj);
        } catch (Exception e) {
            e.printStackTrace();
            addDetailMessage(e.getMessage(),SEVERITY_ERROR);

        }
    }

    public void clear() {
        this.editObj = this.createNewObj();
    }


    public static void addDetailMessage(String message) {
        addDetailMessage(message, null);
    }

    public static void addDetailMessage(String message, FacesMessage.Severity severity) {

        FacesMessage facesMessage = Messages.create("").detail(message).get();
        if (severity != null && severity != FacesMessage.SEVERITY_INFO) {
            facesMessage.setSeverity(severity);
        }
        Messages.add(null, facesMessage);
    }

    /**
     * 调整列表字段的显示与隐藏
     *
     * @param e
     */
    public void onToggle(ColumnToggleEvent e) {
        Integer index = (Integer) e.getData();
        UIColumn column = e.getColumn();
        Visibility visibility = e.getVisibility();
        String header = column.getAriaHeaderText() != null ? column.getAriaHeaderText() : column.getHeaderText();
        Object[] args = {index, header, visibility};
        FacesMessage msg = new FacesMessage(FacesMessage.SEVERITY_INFO, sma.getMessage("dataTable.toggle", args), null);
//        FacesMessage msg = new FacesMessage(FacesMessage.SEVERITY_INFO, "Column " + index + " toggled: " + header + " " + visibility, null);
        FacesContext.getCurrentInstance().addMessage(null, msg);
    }
    //datatable组件属性,用来控制字段filter是否显示
    private boolean globalFilterOnly;

    public void toggleGlobalFilter() {
        setGlobalFilterOnly(!isGlobalFilterOnly());
    }

    public boolean isGlobalFilterOnly() {
        return globalFilterOnly;
    }
}
